Spring Boot自動配置原理
Spring Boot的自動配置註解是@EnableAutoConfiguration, 從上面的@Import的類可以找到下面的自動加載自動配置的映射。
-
org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames(Class, ClassLoader)
-
public static List loadFactoryNames(Class factoryClass, ClassLoader classLoader) {
-
String factoryClassName = factoryClass.getName();
-
try {
-
Enumeration urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
-
lassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
-
List result = new ArrayList();
-
while (urls.hasMoreElements()) {
-
URL url = urls.nextElement();
-
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
-
String factoryClassNames = properties.getProperty(factoryClassName);
-
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
-
}
-
return result;
-
}
-
catch (IOException ex) {
-
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
-
"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
-
}
-
}
這個方法會加載類路徑及所有jar包下META-INF / spring.factories配置中映射的自動配置的類。
-
/**
-
* The location to look for factories.
-
*
Can be present in multiple JAR files.
-
*/
-
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
查看Spring Boot自帶的自動配置的包: spring-boot-autoconfigure-1.5.6.RELEASE.jar,打開其中的META-INF / spring.factories文件會找到自動配置的映射。
-
# Auto Configure
-
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
-
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
-
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
-
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
-
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
-
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
-
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
-
...
再來看看數據源自動配置的實現註解
-
@Configuration
-
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
-
@EnableConfigurationProperties(DataSourceProperties.class)
-
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
-
public class DataSourceAutoConfiguration {
-
...
@ Configuration,@ ConditionalOnClass即自動配置的核心,首先它得是一個配置文件,其次根據類路徑下是否有這個類去自動配置。
自動配置實戰
所以,了解了自動配置的原理,來自己實現一個自動配置的玩意其實很簡單。
添加配置類:
-
import org.slf4j.Logger;
-
import org.springframework.context.EnvironmentAware;
-
import org.springframework.core.env.Environment;
-
import com.oceanpayment.common.utils.logger.LoggerUtils;
-
public class EnvConfig implements EnvironmentAware {
-
private final Logger logger = LoggerUtils.getLogger(this);
-
private Environment env;
-
public String getStringValue(String key) {
-
return env.getProperty(key);
-
}
-
public Long getLongValue(String key) {
-
String value = getStringValue(key);
-
try {
-
return Long.parseLong(value);
-
} catch (Exception e) {
-
logger.error("字符串转换Long失败:{} = {}", key, value);
-
}
-
return 0L;
-
}
-
public int getIntValue(String key) {
-
return getLongValue(key).intValue();
-
}
-
@Override
-
public void setEnvironment(Environment environment) {
-
this.env = environment;
-
}
-
}
添加自動配置類:
-
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-
import org.springframework.context.annotation.Bean;
-
import org.springframework.context.annotation.Configuration;
-
import org.springframework.core.env.PropertyResolver;
-
@Configuration
-
@ConditionalOnClass(PropertyResolver.class)
-
public class EnvAutoConfig {
-
@Bean
-
public EnvConfig envConfig() {
-
return new EnvConfig();
-
}
-
}
創建META-INF / spring.factories文件,添加自動配置映射:
-
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\
-
com.oceanpayment.common.config.env.EnvAutoConfig
這樣就搞定了。
查看自動配置報告
怎麼看自己加的自動配置類有沒有被加載,或者查看所有自動配置激活的和未激活的可以通過以下幾次試查看。
-
spring-boot:在運行環境中加入debug = true變量
-
java -jar xx.jar —debug
-
main方法運行,在VM Argumanets中加入-Ddebug
-
直接在應用程序文件中加入debug = true
-
如果集成了spring-boot-starter-actuator監控,則通過autoconfig端點也可以查看。
啟動後會在控制台看到以下自動配置報告信息:
-
=========================
-
AUTO-CONFIGURATION REPORT
-
=========================
-
Positive matches:
-
-----------------
-
AopAutoConfiguration matched:
-
- @ConditionalOnClass found required classes 'org.springframework.context.annotation.EnableAspectJAutoProxy', 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
-
- @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)
-
...
-
EnvAutoConfig matched:
-
- @ConditionalOnClass found required class 'org.springframework.core.env.PropertyResolver'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
-
ErrorMvcAutoConfiguration matched:
-
- @ConditionalOnClass found required classes 'javax.servlet.Servlet', 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
-
- @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)
-
ErrorMvcAutoConfiguration#basicErrorController matched:
-
- @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.ErrorController; SearchStrategy: current) did not find any beans (OnBeanCondition)
-
...
-
Negative matches:
-
-----------------
-
ActiveMQAutoConfiguration:
-
Did not match:
-
- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
-
AopAutoConfiguration.JdkDynamicAutoProxyConfiguration:
-
Did not match:
-
- @ConditionalOnProperty (spring.aop.proxy-target-class=false) found different value in property 'proxy-target-class' (OnPropertyCondition)
-
ArtemisAutoConfiguration:
-
Did not match:
-
- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory' (OnClassCondition)
-
BatchAutoConfiguration:
-
Did not match:
-
- @ConditionalOnClass did not find required class 'org.springframework.batch.core.launch.JobLauncher' (OnClassCondition)
-
...
正面匹配:已經啟用的自動配置
否定匹配項:未啟用的自動配置
從報告中看到自己添加的EnvAutoConfig已經自動配置了。